﻿#include <iostream>
#include <vector>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>
#include <stdexcept>
#include <memory>
#include <string>  // 包含字符串相关功能
#include <fstream> // 包含文件操作相关功能
#include <chrono>  // 包含时间相关功能

// 线程池类定义
class ThreadPool {
public:
    // 最大支持的线程数量
    static const size_t MAX_THREADS = 128;
    // 最大支持的任务队列大小
    static const size_t MAX_TASKS = 10000;

    // 构造函数，初始化指定数量的工作线程
    // 控制工作线程的生命周期：创建工作线程
    ThreadPool(size_t numThreads) : stop(false) {
        if (numThreads > MAX_THREADS) {
            throw std::runtime_error("Number of threads exceeds the maximum limit of " + std::to_string(MAX_THREADS));
        }
        for (size_t i = 0; i < numThreads; ++i) {
            workers.emplace_back([this] {
                while (true) {
                    std::function<void()> task;

                    {
                        // 锁定任务队列，等待任务或停止信号
                        // 自动从任务队列中获取任务，分配给空闲线程
                        std::unique_lock<std::mutex> lock(queueMutex);
                        condition.wait(lock, [this] { return stop || !tasks.empty(); });
                        if (stop && tasks.empty()) {
                            return; // 如果停止信号已发出且任务队列为空，则退出线程
                        }
                        task = std::move(tasks.front()); // 获取任务
                        tasks.pop(); // 从队列中移除任务
                    }

                    task(); // 执行任务
                }
                });
        }
    }

    // 析构函数，确保所有线程正确停止并等待
    // 控制工作线程的生命周期：停止工作线程
    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            stop = true; // 设置停止信号
        }
        condition.notify_all(); // 通知所有线程
        for (std::thread& worker : workers) {
            worker.join(); // 等待线程结束
        }
    }

    // 提交任务到线程池
    // 支持单个任务提交
    // 返回 std::future 对象，用于等待任务完成并收集返回值
    template<class F, class... Args>
    auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
        using return_type = typename std::result_of<F(Args...)>::type;

        auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
            );

        std::future<return_type> res = task->get_future(); // 获取任务的未来结果
        {
            std::unique_lock<std::mutex> lock(queueMutex);

            if (stop) {
                throw std::runtime_error("enqueue on stopped ThreadPool"); // 如果线程池已停止，抛出异常
            }

            if (tasks.size() >= MAX_TASKS) {
                throw std::runtime_error("Task queue size exceeds the maximum limit of " + std::to_string(MAX_TASKS));
            }

            tasks.emplace([task]() { (*task)(); }); // 将任务添加到队列
        }
        condition.notify_one(); // 通知一个线程
        return res;
    }

    // 设置线程池中的线程数量
    // 调整工作线程数量
    void setThreadCount(size_t newCount) {
        std::unique_lock<std::mutex> lock(queueMutex);
        if (newCount > MAX_THREADS) {
            throw std::runtime_error("Number of threads exceeds the maximum limit of " + std::to_string(MAX_THREADS));
        }
        if (newCount < workers.size()) {
            // 减少线程数量
            // 等待正在执行的任务完成后再减少线程数量
            stop = true;
            condition.notify_all();
            for (size_t i = workers.size(); i > newCount; --i) {
                workers.back().join();  // 等待线程结束
                workers.pop_back();
            }
            stop = false;
        }
        else if (newCount > workers.size()) {
            // 增加线程数量
            for (size_t i = workers.size(); i < newCount; ++i) {
                workers.emplace_back([this] {
                    while (true) {
                        std::function<void()> task;

                        {
                            std::unique_lock<std::mutex> lock(this->queueMutex);
                            this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); });
                            if (this->stop && this->tasks.empty()) {
                                return;
                            }
                            task = std::move(this->tasks.front());
                            this->tasks.pop();
                        }

                        task();
                    }
                    });
            }
        }
    }

private:
    std::vector<std::thread> workers; // 工作线程列表
    std::queue<std::function<void()>> tasks; // 任务队列
    std::mutex queueMutex; // 任务队列的互斥锁
    std::condition_variable condition; // 条件变量，用于线程同步
    bool stop; // 停止信号
};

// 多线程输出测试
// 场景一：多线程输出测试
// 使用 12 个线程
// 调度 1000 个任务
// 每个任务输出不同内容
// 使用 sleep 模拟任务执行时间
void testMultiThreadOutput() {
    ThreadPool pool(12); // 创建一个包含12个线程的线程池

    for (int i = 0; i < 1000; ++i) {
        pool.enqueue([i] {
            std::cout << "Task " << i << " is running" << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟任务执行时间
            });
    }

    std::cout << "All tasks submitted" << std::endl;
}

// 文件操作与任务取消测试
// 场景二：文件操作与任务取消
// 使用 12 个线程
// 调度 1000 个任务
// 每个任务向不同文件写入内容
// 主线程中途取消部分任务
// 验证最终结果正确性
void testFileOperations() {
    ThreadPool pool(12); // 创建一个包含12个线程的线程池

    std::vector<std::future<void>> futures;
    for (int i = 0; i < 1000; ++i) {
        std::string filename = "file_" + std::to_string(i) + ".txt";
        futures.push_back(pool.enqueue([filename] {
            std::ofstream file(filename); // 打开文件
            file << "Content of " << filename << std::endl; // 写入内容
            file.close(); // 关闭文件
            }));
    }

    // 取消部分任务
    // 注意：C++ 标准库中的 std::future 没有提供取消任务的直接方法
    // 这里通过等待部分任务完成来模拟取消操作，实际项目中可能需要其他机制来实现任务取消
    for (int i = 0; i < 500; ++i) {
        futures[i].wait();
    }

    // 验证结果
    for (int i = 500; i < 1000; ++i) {
        std::string filename = "file_" + std::to_string(i) + ".txt";
        std::ifstream file(filename); // 打开文件
        std::string content;
        std::getline(file, content); // 读取内容
        file.close(); // 关闭文件
        if (content != "Content of " + filename) {
            std::cerr << "File " << filename << " has incorrect content" << std::endl;
        }
    }

    std::cout << "File operations test completed" << std::endl;
}

// 数值计算任务测试
// 场景三：数值计算任务
// 使用 12 个线程
// 调度 1000 个计算任务
// 每个任务计算不同的数值
// 主线程收集并累加最终结果
int compute(int value) {
    return value * value; // 计算平方
}

void testNumericalComputations() {
    ThreadPool pool(12); // 创建一个包含12个线程的线程池

    std::vector < std::future<int>> results;
    for (int i = 0; i < 1000; ++i) {
        results.push_back(pool.enqueue(compute, i)); // 提交计算任务
    }

    int sum = 0;
    for (auto& result : results) {
        sum += result.get(); // 获取任务结果并累加
    }

    std::cout << "Sum of results: " << sum << std::endl;
}

// 测试线程池在高负载下的性能
void testHighLoadPerformance() {
    const size_t threadCount = 12;
    const size_t taskCount = 10000; // 增加任务数量以测试高负载性能

    ThreadPool pool(threadCount); // 创建一个包含12个线程的线程池

    auto startTime = std::chrono::high_resolution_clock::now(); // 记录开始时间

    for (size_t i = 0; i < taskCount; ++i) {
        pool.enqueue([i] {
            // 模拟一些计算任务
            volatile int result = i * i;
            (void)result; // 防止未使用变量的警告
            });
    }

    auto endTime = std::chrono::high_resolution_clock::now(); // 记录结束时间
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();

    std::cout << "High load performance test completed in " << duration << " milliseconds" << std::endl;
}

// 测试任务队列满时的行为
void testTaskQueueFullBehavior() {
    const size_t threadCount = 1;
    const size_t taskCount = ThreadPool::MAX_TASKS + 1; // 使任务队列满

    ThreadPool pool(threadCount); // 创建一个包含1个线程的线程池

    try {
        for (size_t i = 0; i < taskCount; ++i) {
            pool.enqueue([i] {
                // 模拟一些计算任务
                volatile int result = i * i;
                (void)result; // 防止未使用变量的警告
                });
        }
    }
    catch (const std::runtime_error& e) {
        std::cout << "Caught exception as expected: " << e.what() << std::endl;
    }
}

int main() {
    // 测试多线程输出
    std::cout << "Starting multi-thread output test..." << std::endl;
    testMultiThreadOutput();

    // 测试文件操作
    std::cout << "Starting file operations test..." << std::endl;
    testFileOperations();

    // 测试数值计算
    std::cout << "Starting numerical computations test..." << std::endl;
    testNumericalComputations();

    // 测试线程池在高负载下的性能
    std::cout << "Starting high load performance test..." << std::endl;
    testHighLoadPerformance();

    // 测试任务队列满时的行为
    std::cout << "Starting task queue full behavior test..." << std::endl;
    testTaskQueueFullBehavior();

    return 0;
}